package rcpexplorer.views;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;

public class WidgetHolder implements IPropertySource {
	private WeakReference<Widget> widgetReference;
	
	
	public WidgetHolder(Widget widget) {
		this.widgetReference = new WeakReference<Widget>(widget);
	}

	public Widget getWidget() {
		return widgetReference.get();
	}

	public Object getEditableValue() {
		return null;
	}

	@SuppressWarnings("unchecked")
	public IPropertyDescriptor[] getPropertyDescriptors() {
		Widget widget = widgetReference.get();
		if (widget != null) {
			try {
				BeanInfo beanInfo = Introspector.getBeanInfo(widget.getClass(), Object.class);
				List<IPropertyDescriptor> propertyDescriptors = new LinkedList<IPropertyDescriptor>();
				if (beanInfo != null) {
					PropertyDescriptor[] propertyDescs = beanInfo.getPropertyDescriptors();
					for (PropertyDescriptor propertyDesc : propertyDescs) {
						Class propertyType = propertyDesc.getPropertyType();
						if (propertyType == null) {
							continue;
						}
						if (propertyType.isPrimitive()
								|| String.class.isAssignableFrom(propertyType)
								|| Boolean.class.isAssignableFrom(propertyType)
								|| Byte.class.isAssignableFrom(propertyType)
								|| Character.class.isAssignableFrom(propertyType)
								|| Double.class.isAssignableFrom(propertyType)
								|| Float.class.isAssignableFrom(propertyType)
								|| Integer.class.isAssignableFrom(propertyType)
								|| Long.class.isAssignableFrom(propertyType)
								|| Short.class.isAssignableFrom(propertyType)
								|| Color.class.isAssignableFrom(propertyType)
								|| Font.class.isAssignableFrom(propertyType)
								|| Point.class.isAssignableFrom(propertyType)
								|| Rectangle.class.isAssignableFrom(propertyType)
								|| RGB.class.isAssignableFrom(propertyType)
								|| FontData.class.isAssignableFrom(propertyType)
								) {
							String name = propertyDesc.getName() + ":" + propertyType.getName();
							if (Color.class.isAssignableFrom(propertyType)) {
								propertyDescriptors.add(new org.eclipse.ui.views.properties.ColorPropertyDescriptor(propertyDesc, name));
							} else {
								propertyDescriptors.add(new org.eclipse.ui.views.properties.PropertyDescriptor(propertyDesc, name));
							}
						}
					}
				}
				return propertyDescriptors.toArray(new IPropertyDescriptor[0]);
			} catch (IntrospectionException e) {
			}
		}
		return new IPropertyDescriptor[0];
	}

	public Object getPropertyValue(Object id) {
		Widget widget = widgetReference.get();
		if (widget != null && (!widget.isDisposed())) {
			if (id instanceof PropertyDescriptor) {
				PropertyDescriptor propertyDesc = (PropertyDescriptor) id;
				Method readMethod = propertyDesc.getReadMethod();
				if (readMethod != null) {
					try {
						Object objectValue = readMethod.invoke(widget);
						if (objectValue != null) {
							return objectValue.toString();
						}
					} catch (IllegalArgumentException e) {
					} catch (IllegalAccessException e) {
					} catch (InvocationTargetException e) {
					}
				}
			}
		}
		return null;
	}

	public boolean isPropertySet(Object id) {
		return false;
	}

	public void resetPropertyValue(Object id) {
		
	}

	public void setPropertyValue(Object id, Object value) {		
	}

}
